#include "cmachine.h"

#include "cevent.h"
#include "cpart.h"
#include "cbuffer.h"

#include <iostream>

#include "lib.h"

const int CMachine::Idle=			0;
const int CMachine::SetingUp=	1;
const int CMachine::Processing=	2;
const int CMachine::Blocked=		3;


CMachine::CMachine()
{
	Status=CMachine::Idle;
	setType(CElement::TYPE_MACHINE);
	machineId=-1;
	NowPart=(CPart*)NULL;
	PreviousPart=(CPart*)NULL;
}

CMachine::~CMachine()
{
}

void CMachine::Respond(CEvent* evt)//在这个函数里设置机器状态
{
	if(getStatus()==CMachine::Idle)
	{
		if(TryPull())
		{
				CEvent* evt2=new CEvent(	getID(),
										CEvent::Machine_Setup_Over,
										evt->getTime()+calcSetupTime()
									   );
				theModel->CollectEvent(evt2);
				setStatus(CMachine::SetingUp);
				if(Debug_Message==1)
				{
					std::cout<<"\nTIME="<<theModel->getCurrentTime()<<std::endl;
					std::cout<<"Machine["<<machineId<<"] Pulled in a Part with type:"<<NowPart->getFinalType()<<" and DueTime:"<<NowPart->getDueTime()<<std::endl;
				}
		}
	}
	else if(getStatus()==CMachine::SetingUp)
	{
		if(evt->getID()==getID() && evt->getType()==CEvent::Machine_Setup_Over)
		{
			
			CEvent* evt3=new CEvent(getID(),CEvent::Machine_Process_Over,evt->getTime()+calcProcessTime());
			theModel->CollectEvent(evt3);
			setStatus(CMachine::Processing);	
			Process();
		}
	}
	else if(getStatus()==CMachine::Processing)
	{
		if(evt->getID()==getID() && evt->getType()==CEvent::Machine_Process_Over)
		{
			CEvent* evt4=new CEvent(getID(),CEvent::Machine_Block_Begin,evt->getTime());
			theModel->CollectEvent(evt4);
			setStatus(CMachine::Blocked);
		}
	}
	else if(getStatus()==CMachine::Blocked)
	{
		if(TryPush())
		{
			CEvent* evt5 =new CEvent(getID(),CEvent::Begin_Idle,evt->getTime());
			theModel->CollectEvent(evt5);
			setStatus(CMachine::Idle);
			if(Debug_Message==1)
				{
					std::cout<<"\nTIME="<<theModel->getCurrentTime()<<std::endl;
					std::cout<<"Machine["<<machineId<<"] Pushed out a Part with type:"<<PreviousPart->getFinalType()<<" and DueTime:"<<PreviousPart->getDueTime()<<std::endl;
				}
		}
	}
	else
	{
		std::cout<<"CMachine::Respond():ERROR. A Wrong Status Detected."<<std::endl;
	}
}

bool CMachine::TryPull()
{
	if(PreviousElements.empty())
	{
		return false;
	}
	else
	{
		std::vector<CElement*>::iterator it=PreviousElements.begin();
		for(;it!=PreviousElements.end();it++)
		{
			bool rs=false;
			if((*it)->getType()==CElement::TYPE_MACHINE)
			{
				rs=Pull((CMachine*)(*it));
			}
			else if((*it)->getType()==CElement::TYPE_BUFFER)
			{
				rs=Pull((CBuffer*)(*it));
			}
			if(rs)
			{
				return true;
			}
		}
	}
	return false;
}

bool CMachine::TryPush()
{
	if(!(NextElements.empty()))
	{
		std::vector<CElement*>::iterator it=NextElements.begin();
		for(;it!=NextElements.end();it++)
		{
			bool rs=false;
			if((*it)->getType()==CElement::TYPE_MACHINE)
			{
				rs=GivePartTo((CMachine*)(*it));
			}
			else if((*it)->getType()==CElement::TYPE_BUFFER)
			{
				rs=GivePartTo((CBuffer*)(*it));
			}
			if(rs)
			{
				PreviousPart->setLastOpTime(theModel->getCurrentTime());
				return true;
			}
		}
	}
	return false;
}

#include "lib.h"

extern int O_1[C_out+1][M+1];	//工艺矩阵，类别i在机器j上的工序编号

extern int p_[NR+1];				//工序i的加工时间，

extern int s_[NR+1][NR+1];		//工序i到j的切换时间

extern int 	R_0_c[n_0+1];	//需求序列类别号码
extern double 	R_0_d[n_0+1];	//需求序列交货期

double CMachine::calcSetupTime()
{
	//1.get Previous Part's Final Type
	//2.get the Operation Number o1 of the Type at This Machine Number, if part is NULL , return 0;
	//3.get the Operation Number o2 of Now part
	//4.return s[o1][o2]
	//
	if(machineId<0)
	{
		std::cout<<"A Machine's ID is not set."<<std::endl;
		return 0.0;
	}
	if(PreviousPart==(CPart*)NULL)
	{
		if(Debug_Message==1)
		{
				std::cout<<"setup time is 0.0"<<std::endl;
		}
		return 0.0;
	}
	else{
		int o1=O_1[PreviousPart->getFinalType()][machineId];
		int o2=O_1[NowPart->getFinalType()][machineId];
		if(Debug_Message==1)
		{
				std::cout<<"setup time is "<<s_[o1][o2]<<std::endl;
		}
		return s_[o1][o2];
	}
}

double CMachine::calcProcessTime()
{
	int o2=O_1[NowPart->getFinalType()][machineId];
	if(Debug_Message==1)
		{
				std::cout<<"Process time is "<<p_[o2]<<std::endl;
		}
	return p_[o2];
}

void CMachine::Process()
{
	int o2=O_1[NowPart->getFinalType()][machineId];
	NowPart->AddOperation(o2);
}





bool CMachine::Pull(CMachine* aM)//从机器处拉得一个零件
{
	if(Status==CMachine::Idle)
	{
		if(aM->getStatus()==CMachine::Blocked)
		{
			CPart* p=(CPart*)NULL;
			p=aM->HandOutPart();
			if(p!=(CPart*)NULL){
				NowPart=p;
				//setStatus(CMachine::SetingUp);
				return true;
			}
		}
		else
		{
			return false;
		}
	}
	return false;//失败
}

bool CMachine::Pull(CBuffer* aB)//从缓冲处拉来一个零件
{
	if(Status==CMachine::Idle)
	{
		if(!(aB->IsEmpty()))
		{
			CPart* p=(CPart*)NULL;
			p=aB->GiveAPartOut();
			if(p!=(CPart*)NULL)
			{
				NowPart=p;
				return true;
			}
		}
	}
	return false;
}
bool CMachine::GivePartTo(CMachine* aM)//将零件送到另一个机器
{
	if(Status==CMachine::Blocked)
	{
		if(aM->getStatus()==CMachine::Idle)
		{
			return aM->Pull(this);
		}
	}
	return false;
}
bool CMachine::GivePartTo(CBuffer* aB)//将零件送到一个缓冲区
{
	if(Status==CMachine::Blocked)
	{
		if(!(aB->IsFull()))
		{
			return aB->GetAPartIn(HandOutPart());
		}
	}
	return false;
}



int CMachine::getStatus()
{
	return Status;
}

void CMachine::setStatus(int st)
{
	Status=st;
}

CPart* CMachine::HandOutPart()//给出零件
{
	CPart* p=(CPart*)NULL;
	if(Status==CMachine::Blocked)
	{
		p=NowPart;
		PreviousPart=NowPart;
		NowPart=(CPart*)NULL;
		CEvent* evt=new CEvent(getID(),CEvent::Machine_Block_Over,theModel->getCurrentTime());
		theModel->CollectEvent(evt);
		//setStatus(CMachine::Idle);//留到其响应函数中设置状态
	}
	return p;
}


void CMachine::setMachineID(int id)
{
	machineId=id;
}